package com.zenithmind.library.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import com.zenithmind.common.result.ResultCode;
import com.zenithmind.library.mapper.BookMapper;
import com.zenithmind.library.pojo.domain.Book;
import com.zenithmind.library.pojo.dto.BookCreateDTO;
import com.zenithmind.library.pojo.dto.BookUpdateDTO;
import com.zenithmind.library.pojo.query.BookQuery;
import com.zenithmind.library.pojo.vo.BookDetailVO;
import com.zenithmind.library.pojo.vo.BookVO;
import com.zenithmind.library.service.BookService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 图书服务实现类
 * 
 * @author ZenithMind
 * @since 2024-06-14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BookServiceImpl extends ServiceImpl<BookMapper, Book> implements BookService {

    private final BookMapper bookMapper;

    @Override
    @Cacheable(value = "books", key = "'page:' + #query.hashCode()")
    public PageResult<BookVO> getBookPage(BookQuery query) {
        log.info("分页查询图书，查询条件：{}", query);

        Page<BookVO> page = query.toPage();
        IPage<BookVO> result = bookMapper.selectBookPage(page, query);

        return PageResult.of(result.getRecords(), result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    @Cacheable(value = "books", key = "'detail:' + #id")
    public BookDetailVO getBookDetail(String id) {
        log.info("查询图书详情，ID：{}", id);
        
        BookDetailVO bookDetail = bookMapper.selectBookDetailById(id);
        if (bookDetail == null) {
            throw new RuntimeException("图书不存在");
        }
        
        return bookDetail;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "books", allEntries = true)
    public Result<BookVO> createBook(BookCreateDTO createDTO) {
        log.info("创建图书，数据：{}", createDTO);
        
        // 检查ISBN是否已存在
        if (checkIsbnExists(createDTO.getIsbn(), null)) {
            return Result.fail(ResultCode.CONFLICT.getCode(), "ISBN已存在", null);
        }
        
        // 转换为实体对象
        Book book = new Book();
        BeanUtils.copyProperties(createDTO, book);
        book.setAvailableCopies(createDTO.getTotalCopies());
        book.setBorrowedCopies(0);
        book.setTotalBorrowCount(0L);
        book.setReviewCount(0);
        book.setStatus(1); // 默认上架
        book.setCreateTime(LocalDateTime.now());
        book.setUpdateTime(LocalDateTime.now());
        
        // 保存图书
        boolean saved = save(book);
        if (!saved) {
            return Result.fail(ResultCode.FAIL.getCode(), "创建图书失败", null);
        }
        
        // 返回创建的图书信息
        BookVO bookVO = convertToVO(book);
        return Result.success(bookVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "books", allEntries = true)
    public Result<BookVO> updateBook(String id, BookUpdateDTO updateDTO) {
        log.info("更新图书，ID：{}，数据：{}", id, updateDTO);
        
        // 检查图书是否存在
        Book existingBook = getById(id);
        if (existingBook == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书不存在", null);
        }
        
        // 检查ISBN是否已被其他图书使用
        if (StringUtils.hasText(updateDTO.getIsbn()) && 
            checkIsbnExists(updateDTO.getIsbn(), id)) {
            return Result.fail(ResultCode.CONFLICT.getCode(), "ISBN已被其他图书使用", null);
        }
        
        // 更新图书信息
        Book book = new Book();
        BeanUtils.copyProperties(updateDTO, book);
        book.setId(id);
        book.setUpdateTime(LocalDateTime.now());
        
        boolean updated = updateById(book);
        if (!updated) {
            return Result.fail(ResultCode.FAIL.getCode(), "更新图书失败", null);
        }
        
        // 返回更新后的图书信息
        Book updatedBook = getById(id);
        BookVO bookVO = convertToVO(updatedBook);
        return Result.success(bookVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "books", allEntries = true)
    public Result<Void> deleteBook(String id) {
        log.info("删除图书，ID：{}", id);
        
        // 检查图书是否存在
        Book book = getById(id);
        if (book == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书不存在", null);
        }
        
        // 检查是否有未归还的借阅记录
        if (book.getBorrowedCopies() != null && book.getBorrowedCopies() > 0) {
            return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "该图书还有未归还的副本，无法删除", null);
        }
        
        // 逻辑删除图书
        boolean deleted = removeById(id);
        if (!deleted) {
            return Result.fail(ResultCode.FAIL.getCode(), "删除图书失败", null);
        }
        
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "books", allEntries = true)
    public Result<Void> batchDeleteBooks(List<String> ids) {
        log.info("批量删除图书，IDs：{}", ids);
        
        // 检查是否有未归还的借阅记录
        for (String id : ids) {
            Book book = getById(id);
            if (book != null && book.getBorrowedCopies() != null && book.getBorrowedCopies() > 0) {
                return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "图书《" + book.getTitle() + "》还有未归还的副本，无法删除", null);
            }
        }
        
        // 批量删除
        boolean deleted = removeByIds(ids);
        if (!deleted) {
            return Result.fail(ResultCode.FAIL.getCode(), "批量删除图书失败", null);
        }
        
        return Result.success();
    }

    @Override
    @CacheEvict(value = "books", allEntries = true)
    public Result<Void> publishBook(String id) {
        log.info("上架图书，ID：{}", id);
        return updateBookStatus(id, 1);
    }

    @Override
    @CacheEvict(value = "books", allEntries = true)
    public Result<Void> unpublishBook(String id) {
        log.info("下架图书，ID：{}", id);
        return updateBookStatus(id, 0);
    }

    @Override
    @CacheEvict(value = "books", allEntries = true)
    public Result<Void> recommendBook(String id) {
        log.info("推荐图书，ID：{}", id);
        return updateRecommendStatus(id, 1);
    }

    @Override
    @CacheEvict(value = "books", allEntries = true)
    public Result<Void> unrecommendBook(String id) {
        log.info("取消推荐图书，ID：{}", id);
        return updateRecommendStatus(id, 0);
    }

    @Override
    @Cacheable(value = "books", key = "'isbn:' + #isbn")
    public BookVO getBookByIsbn(String isbn) {
        log.info("根据ISBN查询图书，ISBN：{}", isbn);
        return bookMapper.selectBookByIsbn(isbn);
    }

    @Override
    public PageResult<BookVO> getBooksByCategory(String categoryId, BookQuery query) {
        log.info("根据分类查询图书，分类ID：{}，查询条件：{}", categoryId, query);

        Page<BookVO> page = query.toPage();
        IPage<BookVO> result = bookMapper.selectBooksByCategory(page, categoryId, query);

        return PageResult.of(result.getRecords(), result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    public PageResult<BookVO> getBooksByAuthor(String authorId, BookQuery query) {
        log.info("根据作者查询图书，作者ID：{}，查询条件：{}", authorId, query);

        Page<BookVO> page = query.toPage();
        IPage<BookVO> result = bookMapper.selectBooksByAuthor(page, authorId, query);

        return PageResult.of(result.getRecords(), result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    public PageResult<BookVO> getBooksByPublisher(String publisherId, BookQuery query) {
        log.info("根据出版社查询图书，出版社ID：{}，查询条件：{}", publisherId, query);

        Page<BookVO> page = query.toPage();
        IPage<BookVO> result = bookMapper.selectBooksByPublisher(page, publisherId, query);

        return PageResult.of(result.getRecords(), result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    public PageResult<BookVO> searchBooks(String keyword, BookQuery query) {
        log.info("搜索图书，关键词：{}，查询条件：{}", keyword, query);

        Page<BookVO> page = query.toPage();
        IPage<BookVO> result = bookMapper.searchBooks(page, keyword, query);

        return PageResult.of(result.getRecords(), result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    @Cacheable(value = "books", key = "'recommended:' + #query.hashCode()")
    public PageResult<BookVO> getRecommendedBooks(BookQuery query) {
        log.info("获取推荐图书，查询条件：{}", query);

        Page<BookVO> page = query.toPage();
        IPage<BookVO> result = bookMapper.selectRecommendedBooks(page, query);

        return PageResult.of(result.getRecords(), result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    @Cacheable(value = "books", key = "'new:' + #query.hashCode()")
    public PageResult<BookVO> getNewBooks(BookQuery query) {
        log.info("获取新书，查询条件：{}", query);

        Page<BookVO> page = query.toPage();
        IPage<BookVO> result = bookMapper.selectNewBooks(page, query);

        return PageResult.of(result.getRecords(), result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    @Cacheable(value = "books", key = "'popular:' + #query.hashCode()")
    public PageResult<BookVO> getPopularBooks(BookQuery query) {
        log.info("获取热门图书，查询条件：{}", query);

        Page<BookVO> page = query.toPage();
        IPage<BookVO> result = bookMapper.selectPopularBooks(page, query);

        return PageResult.of(result.getRecords(), result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "books", allEntries = true)
    public Result<Void> updateBookStock(String bookId, Integer totalCopies, Integer availableCopies) {
        log.info("更新图书库存，图书ID：{}，总库存：{}，可借阅库存：{}", bookId, totalCopies, availableCopies);
        
        int updated = bookMapper.updateBookStock(bookId, totalCopies, availableCopies);
        if (updated == 0) {
            return Result.fail(ResultCode.FAIL.getCode(), "更新图书库存失败", null);
        }
        
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "books", allEntries = true)
    public Result<Void> incrementBorrowCount(String bookId) {
        log.info("增加图书借阅次数，图书ID：{}", bookId);
        
        int updated = bookMapper.incrementBorrowCount(bookId);
        if (updated == 0) {
            return Result.fail(ResultCode.FAIL.getCode(), "更新借阅次数失败", null);
        }
        
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "books", allEntries = true)
    public Result<Void> updateBookRating(String bookId, Double rating) {
        log.info("更新图书评分，图书ID：{}，评分：{}", bookId, rating);
        
        // 这里应该重新计算评分和评价数量
        // 简化实现，实际应该查询所有评价重新计算
        int updated = bookMapper.updateBookRating(bookId, rating, null);
        if (updated == 0) {
            return Result.fail(ResultCode.FAIL.getCode(), "更新图书评分失败", null);
        }
        
        return Result.success();
    }

    @Override
    public Result<String> importBooks(List<BookCreateDTO> books) {
        log.info("导入图书数据，数量：{}", books.size());
        
        // TODO: 实现批量导入逻辑
        // 1. 数据验证
        // 2. 批量插入
        // 3. 返回导入结果
        
        return Result.success("导入成功");
    }

    @Override
    public Result<String> exportBooks(BookQuery query) {
        log.info("导出图书数据，查询条件：{}", query);
        
        // TODO: 实现数据导出逻辑
        // 1. 查询数据
        // 2. 生成Excel文件
        // 3. 返回文件路径
        
        return Result.success("/exports/books_" + System.currentTimeMillis() + ".xlsx");
    }

    /**
     * 检查ISBN是否已存在
     */
    private boolean checkIsbnExists(String isbn, String excludeId) {
        LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Book::getIsbn, isbn);
        if (StringUtils.hasText(excludeId)) {
            wrapper.ne(Book::getId, excludeId);
        }
        return count(wrapper) > 0;
    }

    /**
     * 更新图书状态
     */
    private Result<Void> updateBookStatus(String id, Integer status) {
        Book book = new Book();
        book.setId(id);
        book.setStatus(status);
        book.setUpdateTime(LocalDateTime.now());
        
        boolean updated = updateById(book);
        if (!updated) {
            return Result.fail(ResultCode.FAIL.getCode(), "更新图书状态失败", null);
        }
        
        return Result.success();
    }

    /**
     * 更新推荐状态
     */
    private Result<Void> updateRecommendStatus(String id, Integer isRecommended) {
        Book book = new Book();
        book.setId(id);
        book.setIsRecommended(isRecommended);
        book.setUpdateTime(LocalDateTime.now());
        
        boolean updated = updateById(book);
        if (!updated) {
            return Result.fail(ResultCode.FAIL.getCode(), "更新推荐状态失败", null);
        }
        
        return Result.success();
    }

    /**
     * 转换为VO对象
     */
    private BookVO convertToVO(Book book) {
        BookVO bookVO = new BookVO();
        BeanUtils.copyProperties(book, bookVO);
        return bookVO;
    }
}
